package ua.pp.bizon.yandex.uploader.atom;

import ua.pp.bizon.yandex.api.IAppService;
import ua.pp.bizon.yandex.api.IHTTPUtils;
import ua.pp.bizon.yandex.api.IUserData;
import ua.pp.bizon.yandex.api.IUserDataManager;
import ua.pp.bizon.yandex.api.JobInfo;
import ua.pp.bizon.yandex.api.ObjectLookup;
import ua.pp.bizon.yandex.api.cache.IHTTPCache;
import ua.pp.bizon.yandex.api.impl.Activity;
import ua.pp.bizon.yandex.api.impl.EventSupport;
import ua.pp.bizon.yandex.api.impl.EventSupport.ChangeListener;
import ua.pp.bizon.yandex.api.impl.JobExecutor;

import java.io.StringReader;
import java.util.List;

import org.apache.abdera.model.Document;
import org.apache.abdera.model.Element;
import org.apache.abdera.parser.stax.FOMParserFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.HttpResponseException;

public class AppServiceFactory implements IAppService {

	protected final class ReReadJob implements JobInfo {
		@Override
		public void run() {
			create();
		}

		@Override
		public String toString() {
			return "AppServiceFactory#reread()";
		}

		public ua.pp.bizon.yandex.api.impl.Element getState() {
			ua.pp.bizon.yandex.api.impl.Element element = new ua.pp.bizon.yandex.api.impl.Element();
			element.setActivity(Activity.READ_SERVICE_DOCUMENT);
			return element;
		}
	}

	private AppService service;
	private static Log log = LogFactory.getLog(AppServiceFactory.class);
	private EventSupport support = new EventSupport();

	/*
	 * (non-Javadoc)
	 * 
	 * @see ua.pp.bizon.yandex.uploader.atom.IAppService#create()
	 */
	@Override
	public AppService create() {
		service = null;
		ObjectLookup.lookup(IHTTPCache.class).clear();
		get();
		support.tourchListeners();
		return service;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ua.pp.bizon.yandex.uploader.atom.IAppService#get()
	 */
	@Override
	public synchronized AppService get() {
		if (service != null) {
			return service;
		}
		log.debug("getting service document");
		IUserData defaultEnv = ObjectLookup.lookup(IUserDataManager.class).get();
		if (defaultEnv == null) {
			log.fatal("no user data");
			return null;
		}
		String url = AppService.SERVICE_URL;
		service = new AppService();
		String res = null;
		try {
			res = ObjectLookup.lookup(IHTTPUtils.class).get(url, defaultEnv.getToken());
		} catch (HttpResponseException e) {
			log.fatal(e.getMessage(), e);
			throw new UnsupportedOperationException("please check the service URL and internet connection");
		}
		log.debug("service document has being got");
		Document<Element> document = new FOMParserFactory().getParser().parse(new StringReader(res));
		List<Element> tokens = document.getRoot().getElements().get(0).getElements();
		for (Element e : tokens) {
			if (e.getQName().getLocalPart().equals("title")) {
				service.setTitle(e.getText());
			} else if (e.getQName().getLocalPart().equals("collection")) {
				String id = e.getAttributeValue("id");
				service.getLinks().put(id, new AppLink(e));
				log.trace("link to " + e + " has being added");
			}
		}
		log.debug("service document has being parsed");
		return service;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * ua.pp.bizon.yandex.uploader.atom.IAppService#addChangeListener(ua.pp.
	 * bizon.yandex.api.EventSupport.ChangeListener)
	 */
	@Override
	public void addChangeListener(ChangeListener leftTree) {
		support.addListener(leftTree);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * ua.pp.bizon.yandex.uploader.atom.IAppService#removeChangeListener(ua.
	 * pp.bizon.yandex.api.EventSupport.ChangeListener)
	 */
	@Override
	public void removeChangeListener(ChangeListener leftTree) {
		support.removeListener(leftTree);
	}

	@Override
	public void reread() {
		ObjectLookup.lookup(JobExecutor.class).exec(new ReReadJob());
	}

}
